package Module;

import Communication.TaskForModule;
import LiftEngine.Lift;
import java.util.LinkedList;
import Const.*;
import Communication.TaskForServer;
/**
 *
 * Class description goes here.
 *
 * @author Kamil Gajowy
 */
public class ModuleSteeringAlgorithm {

    private int nextTaskID = 0;

    /**
    * Default constructor.
    */

    public ModuleSteeringAlgorithm(){
        
    }
        //input - dane wyciagane z clientLift
        //clientList.getWaitingQueue().getClientList();       //osoby z wcisnietym przyciskiem wolania windy
        //clientList.getTravelingQueue().getClientList();     //osoby w windzie

        //output -- dane modyfikowane w liftRef

        //liftRef.getTask().setPersonToPackOnFloorX(floorNo, count);
        //liftRef.getTask().setPersonToUnloadOnFloorX(floorNo, count);
        //liftRef.setNextFloor(...);
        //liftRef.setLiftDirection(...);


    synchronized void update(Lift liftRef, LinkedList<TaskForModule> taskList, LinkedList<TaskForServer> tasksForServer){ //throws InterruptedException {
        //System.out.println(taskList.size() + "\t" + tasksForServer.size() + "\t" + liftRef.getCurrentFloor());

        synchronized(taskList){
            for(int i = ModuleClient.getCurrentTaskNumber(); i<taskList.size(); i++)
            {
                if(taskList.get(i).getAction() == TaskConst.ActionPersonJoinedWaiting)
                {
                    System.out.println("CIASTKO!");
                    //czy ten ktos jest po drodze , zeby go zabrac?
                    if (tasksForServer.size() >= 1){
                        int start = liftRef.getCurrentFloor();
                        int end = tasksForServer.getFirst().getFloorToTravel();
                        int here = taskList.get(i).getClient().getCurrentFloor();
                        if ( start > end ){
                            //jedzie w dol
                            if ( here < start ){
                                //ok, po drodze!
                                boolean check = false;
                                int z;  //sprawdzamy task ZA NAMI
                                int oldID = 0;
                                System.out.println("____________going up.");
                                for ( z = 0 ; z < tasksForServer.size() ; ++z ){
                                    System.out.println("^ Compare curr floor " +taskList.get(i).getClient().getCurrentFloor() +
                                            "\twith travel target "+ tasksForServer.get(z).getFloorToTravel());
                                    if ( tasksForServer.get(z).getFloorToTravel() <
                                         taskList.get(i).getClient().getCurrentFloor()   ){
                                        //System.out.println("____________found place:"+z);
                                        //System.out.println("____________z+1 travelTO:"+tasksForServer.get(z).getFloorToTravel());
                                        //System.out.println("____________currFloor:"+taskList.get(i).getClient().getCurrentFloor());

                                        oldID = tasksForServer.get(z).getTaskID();
                                        correctTaskIDAfter(z,tasksForServer);
                                        check = true;
                                        break;
                                    }
                                }

                                if (!check){
                                    ++nextTaskID;
                                    oldID = nextTaskID;
                                }


                                //correctAllTaskID(tasksForServer);
                                tasksForServer.add(z,new TaskForServer(
                                    taskList.get(i).getClient().getId(),
                                    taskList.get(i).getClient().getCurrentFloor(),
                                    TaskConst.ActionLoadPerson, oldID));
                                if(check){
                                    nextTaskID++;
                                }
                                ModuleClient.currentTaskNumber++;
                                System.out.println("moze zabierzemy kogos po drodze?");
                            }
                            else{
                                //nie po drodze, dodaj chuja na koncu :P
                                ++nextTaskID;
                                tasksForServer.add(new TaskForServer(
                                    taskList.get(i).getClient().getId(),
                                    taskList.get(i).getClient().getCurrentFloor(),
                                    TaskConst.ActionLoadPerson, nextTaskID));
                                ModuleClient.currentTaskNumber++;
                                System.out.println("aaa nie po drodze mi, ssij");
                            }
                        }
                        else {
                            //jedzie w gore
                            if ( here > start ){
                                //ok, po drodze!
                                boolean check = false;
                                int z;  //sprawdzamy task ZA NAMI
                                int oldID = 0;
                                System.out.println("____________going up.");
                                for ( z = 0 ; z < tasksForServer.size() ; ++z ){
                                    System.out.println("^ Compare curr floor " +taskList.get(i).getClient().getCurrentFloor() +
                                            "\twith travel target "+ tasksForServer.get(z).getFloorToTravel());
                                    if ( tasksForServer.get(z).getFloorToTravel() >
                                         taskList.get(i).getClient().getCurrentFloor()   ){
                                        //System.out.println("____________found place:"+z);
                                        //System.out.println("____________z+1 travelTO:"+tasksForServer.get(z).getFloorToTravel());
                                        //System.out.println("____________currFloor:"+taskList.get(i).getClient().getCurrentFloor());
                                        
                                        oldID = tasksForServer.get(z).getTaskID();
                                        correctTaskIDAfter(z,tasksForServer);
                                        check = true;
                                        break;
                                    }
                                }

                                if (!check){
                                    ++nextTaskID;
                                    oldID = nextTaskID;
                                }

                                
                                //correctAllTaskID(tasksForServer);
                                tasksForServer.add(z,new TaskForServer(
                                    taskList.get(i).getClient().getId(),
                                    taskList.get(i).getClient().getCurrentFloor(),
                                    TaskConst.ActionLoadPerson, oldID));
                                if(check){
                                    nextTaskID++;
                                }
                                ModuleClient.currentTaskNumber++;
                                System.out.println("moze zabierzemy kogos po drodze?");
                            } else {
                                //nie po drodze, dodaj chuja na koncu :P
                                ++nextTaskID;
                                tasksForServer.add(new TaskForServer(
                                    taskList.get(i).getClient().getId(),
                                    taskList.get(i).getClient().getCurrentFloor(),
                                    TaskConst.ActionLoadPerson, nextTaskID));
                                ModuleClient.currentTaskNumber++;
                                System.out.println("aaa nie po drodze mi, ssij");
                            }
                        }
                    } else {
                        // za malo taskow zeby rozwazac
                        ++nextTaskID;
                        tasksForServer.add(new TaskForServer(
                            taskList.get(i).getClient().getId(),
                            taskList.get(i).getClient().getCurrentFloor(),
                            TaskConst.ActionLoadPerson, nextTaskID));
                        ModuleClient.currentTaskNumber++;
                        System.out.println("ni ma nikogo :( ");
                    }
                }

/* TASK UNLOADING ------------------------------------------------------*/

                if(taskList.get(i).getAction() == TaskConst.ActionPersonJoinedTraveling)
                {

                    System.out.println("2 CIASTKO 2!");
                    //czy ten ktos jest po drodze , zeby go zabrac?
                    if (tasksForServer.size() >= 1){
                        int start = liftRef.getCurrentFloor();
                        int end = tasksForServer.getFirst().getFloorToTravel();
                        int here = taskList.get(i).getClient().getDesiredFloor();
                        if ( start > end ){
                            //jedzie w dol
                            if ( here < start ){
                                //ok, po drodze!
                                boolean check = false;
                                int z;  //sprawdzamy task ZA NAMI
                                int oldID = 0;
                                System.out.println("______U______going up.");
                                for ( z = 0 ; z < tasksForServer.size() ; ++z ){
                                    System.out.println("^ UN Compare curr floor " +taskList.get(i).getClient().getDesiredFloor() +
                                            "\twith travel target "+ tasksForServer.get(z).getFloorToTravel());
                                    if ( tasksForServer.get(z).getFloorToTravel() <
                                         taskList.get(i).getClient().getDesiredFloor()   ){
                                        //System.out.println("____________found place:"+z);
                                        //System.out.println("____________z+1 travelTO:"+tasksForServer.get(z).getFloorToTravel());
                                        //System.out.println("____________currFloor:"+taskList.get(i).getClient().getCurrentFloor());

                                        oldID = tasksForServer.get(z).getTaskID();
                                        correctTaskIDAfter(z,tasksForServer);
                                        check = true;
                                        break;
                                    }
                                }

                                if (!check){
                                    ++nextTaskID;
                                    oldID = nextTaskID;
                                }


                                //correctAllTaskID(tasksForServer);
                                tasksForServer.add(z,new TaskForServer(
                                    taskList.get(i).getClient().getId(),
                                    taskList.get(i).getClient().getDesiredFloor(),
                                    TaskConst.ActionUnloadPerson, oldID));
                                if(check){
                                    nextTaskID++;
                                }
                                ModuleClient.currentTaskNumber++;
                            }
                            else{
                                //nie po drodze, dodaj chuja na koncu :P
                                ++nextTaskID;
                                tasksForServer.add(new TaskForServer(
                                    taskList.get(i).getClient().getId(),
                                    taskList.get(i).getClient().getDesiredFloor(),
                                    TaskConst.ActionUnloadPerson, nextTaskID));
                                ModuleClient.currentTaskNumber++;
                            }
                        }
                        else {
                            //jedzie w gore
                            if ( here > start ){
                                //ok, po drodze!
                                boolean check = false;
                                int z;  //sprawdzamy task ZA NAMI
                                int oldID = 0;
                                System.out.println("______U______going up.");
                                for ( z = 0 ; z < tasksForServer.size() ; ++z ){
                                    System.out.println("^ U Compare curr floor " +taskList.get(i).getClient().getDesiredFloor() +
                                            "\twith travel target "+ tasksForServer.get(z).getFloorToTravel());
                                    if ( tasksForServer.get(z).getFloorToTravel() >
                                         taskList.get(i).getClient().getDesiredFloor()   ){
                                        //System.out.println("____________found place:"+z);
                                        //System.out.println("____________z+1 travelTO:"+tasksForServer.get(z).getFloorToTravel());
                                        //System.out.println("____________currFloor:"+taskList.get(i).getClient().getCurrentFloor());

                                        oldID = tasksForServer.get(z).getTaskID();
                                        correctTaskIDAfter(z,tasksForServer);
                                        check = true;
                                        break;
                                    }
                                }

                                if (!check){
                                    ++nextTaskID;
                                    oldID = nextTaskID;
                                }


                                //correctAllTaskID(tasksForServer);
                                tasksForServer.add(z,new TaskForServer(
                                    taskList.get(i).getClient().getId(),
                                    taskList.get(i).getClient().getDesiredFloor(),
                                    TaskConst.ActionUnloadPerson, oldID));
                                if(check){
                                    nextTaskID++;
                                }
                                ModuleClient.currentTaskNumber++;
                            } else {
                                //nie po drodze, dodaj chuja na koncu :P
                                ++nextTaskID;
                                tasksForServer.add(new TaskForServer(
                                    taskList.get(i).getClient().getId(),
                                    taskList.get(i).getClient().getDesiredFloor(),
                                    TaskConst.ActionUnloadPerson, nextTaskID));
                                ModuleClient.currentTaskNumber++;
                                System.out.println("aaa nie po drodze mi, ssij");
                            }
                        }
                    } else {
                        // za malo taskow zeby rozwazac
                        ++nextTaskID;
                        tasksForServer.add(new TaskForServer(
                            taskList.get(i).getClient().getId(),
                            taskList.get(i).getClient().getDesiredFloor(),
                            TaskConst.ActionUnloadPerson, nextTaskID));
                        ModuleClient.currentTaskNumber++;
                        System.out.println("ni ma nikogo :( ");
                    }
                }
                if(taskList.get(i).getAction() == TaskConst.ActionPersonLeftTheLift)
                {
                        ModuleClient.currentTaskNumber++;
                }
            }


        }
    }

    private int switchDirection(Lift liftRef)
    {
        if(liftRef.getLiftDirection() == ServerConst.LiftDirectionDown) return ServerConst.LiftDirectionUp;
        if(liftRef.getLiftDirection() == ServerConst.LiftDirectionUp)   return ServerConst.LiftDirectionDown;
        // i chuj
        return -1000;

    }
    private int getDirectionBasedOnFloor(Lift liftRef, int whereTo )
    {
        if(liftRef.getCurrentFloor() > whereTo)
        {
            return ServerConst.LiftDirectionDown;
        }
        if(liftRef.getCurrentFloor() <= whereTo)
        {
            return ServerConst.LiftDirectionUp;
        }

        return -1000;
    }

    private void correctAllTaskID(LinkedList<TaskForServer> tasksForServer) {
        int i;
        for ( i = 0 ; i < tasksForServer.size() ; ++ i ){
            int now = tasksForServer.get(i).getTaskID();
            ++now;
            tasksForServer.get(i).setTaskID(now);
        }
    }

    private void correctTaskIDAfter(int z, LinkedList<TaskForServer> tasksForServer) {
        int i;
        for ( i = z ; i < tasksForServer.size() ; ++ i ){
            int now = tasksForServer.get(i).getTaskID();
            ++now;
            tasksForServer.get(i).setTaskID(now);
        }
    }

}//end class
